﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Summer.Network;
using Proto;
using Serilog;
using GameServer.Model;
using GameServer.Mgr;
using Summer;
using GameServer.Database;
using GameServer.Network;
using static FreeSql.Internal.GlobalFilter;
using Google.Protobuf;

namespace GameServer.Service
{
    /// <summary>
    /// 玩家服务
    /// 注册，登录，创建角色，进入游戏
    /// </summary>
    public class UserService : Singleton<UserService>
    {
        

        public void Start()
        {
            MessageRouter.Instance.Subscribe<GameEnterRequest>(_GameEnterRequest);
            //消息订阅：用户登录请求
            MessageRouter.Instance.Subscribe<UserLoginRequest>(OnUserLoginRequest);
            //消息订阅：用户注册录请求
            MessageRouter.Instance.Subscribe<UserRegisterRequest>(OnUserRegisterRequest);
            //玩家角色创建请求
            MessageRouter.Instance.Subscribe<CharacterCreateRequest>(OnCharacterCreateRequest);
            //玩家角色删除请求
            MessageRouter.Instance.Subscribe<CharacterDeleteRequest>(OnCharacterDeleteRequest);
            //玩家角色列表
            MessageRouter.Instance.Subscribe<CharacterListRequest>(OnCharacterListRequest);
            //玩家使用的技能列表
            MessageRouter.Instance.Subscribe<NCharacterUsingSkillRequest>(OnCharacterUsingSkillRequest);
            //玩家复活
            MessageRouter.Instance.Subscribe<ReviseRequest>(OnReviseRequest);
            //玩家切换场景
            MessageRouter.Instance.Subscribe<SpaceEnterResponse>(OnSpaceEnterResponse);
            //玩家捡起来东西
            MessageRouter.Instance.Subscribe<PickupItemRequest>(OnPickupItemRequest);
            //背包请求
            MessageRouter.Instance.Subscribe<InventoryRequest>(OnInventoryRequest);
            //穿戴了装备请求
            MessageRouter.Instance.Subscribe<WareEquipmentRequest>(OnWareEquipmentRequest);
            //丢弃了装备请求
            MessageRouter.Instance.Subscribe<ItemThrowInSpaceRequest>(OnItemThrowInSpaceRequest);
            //丢弃了装备请求
            MessageRouter.Instance.Subscribe<ConsumableUseRequest>(OnConsumableUseRequest);
        }

        private void OnConsumableUseRequest(Connection sender, ConsumableUseRequest msg)
        {
            var chr = sender.Get<Session>()?.Character;
            if (chr == null) return;
            chr.knapsack.RemoveItem(msg.ItemID, msg.Amount);
            ItemWareThrowInSpaceResponse response = new ItemWareThrowInSpaceResponse();
            response.Equip = true;
            response.ItemID = msg.ItemID;
            response.Amount = 1;
            response.EntityID = chr.entityId;
            chr.Space.Broadcast(response);
        }

        private void OnItemThrowInSpaceRequest(Connection sender, ItemThrowInSpaceRequest msg)
        {
            var chr = sender.Get<Session>()?.Character;
            if (chr == null) return;
            chr.knapsack.RemoveItem(msg.ItemID, msg.Amount);
            chr.Space.ChuanJianWuPing(msg.ItemID, chr.Position, chr.Direction);
            CharacterManager.Instance.Save();
        }

        private void OnWareEquipmentRequest(Connection sender, WareEquipmentRequest msg)
        {
            var chr = sender.Get<Session>()?.Character;
            if (chr == null) return;
            if (msg.CanelEquipID != 0)
            {
                chr.knapsack.AddItem(msg.CanelEquipID);
                chr.wareKnapsack.RemoveItem(msg.CanelEquipID);
                ItemWareThrowInSpaceResponse response = new ItemWareThrowInSpaceResponse();
                response.Equip = false;
                response.ItemID = msg.CanelEquipID;
                response.Amount = 1;
                response.EntityID = chr.entityId;
                chr.Space.Broadcast(response);
            }
            if (msg.EquipID != 0)
            {
                chr.knapsack.RemoveItem(msg.EquipID);
                chr.wareKnapsack.AddItem(msg.EquipID);
                ItemWareThrowInSpaceResponse response = new ItemWareThrowInSpaceResponse();
                response.ItemID = msg.EquipID;
                response.Amount = 1;
                response.Equip = true;
                response.EntityID = chr.entityId;
                chr.Space.Broadcast(response);
            }
            CharacterManager.Instance.Save();
        }

        private void OnInventoryRequest(Connection sender, InventoryRequest msg)
        {
            var chr = sender.Get<Session>()?.Character;
            if (chr == null) return;
            InventoryResponse resp=new InventoryResponse();
            if (msg.QueryKnapsack)
            {
                resp.KnapsackInfo=chr.knapsack.InventoryInfo;
            }
            if (msg.QueryWarehouse)
            {
                resp.WarehouseInfo=chr.wareKnapsack.InventoryInfo;
            }
            sender.Send(resp);
        }

        private void OnPickupItemRequest(Connection sender, PickupItemRequest msg)
        {
            var chr = sender.Get<Session>()?.Character;
            if (chr == null) return;

            var itemEntity = EntityManager.Instance.GetNearstItem(chr.Space.Id, chr.Position, 2000);
            if (itemEntity == null) return;
            for (int i = 0; i < itemEntity.Count; i++)
            {
                chr.knapsack.AddItem(itemEntity[i].ID);
                chr.Space.ItemLeave(itemEntity[i]);
            }
            CharacterManager.Instance.Save();
            Log.Information("玩家拾取物品Chr[{0}],背包[{1}]", chr.entityId, chr.knapsack.InventoryInfo);
        }

        private void OnSpaceEnterResponse(Connection sender, SpaceEnterResponse msg)
        {
            Character character = sender.Get<Session>().Character;
            Vector3Int targetPosition;
            if (msg.SpaceId == 6)
            {
                targetPosition = new Vector3Int(14754, 0, 69047);
            }
            else if (msg.SpaceId == 4)
            {
                targetPosition = new Vector3Int(191280, 15140, 128970);
            }
            else
            {
                targetPosition = new Vector3Int(14754, 0, 69047);
            }
            character.TelportSpace(sender, SpaceManager.Instance.GetSpace(msg.SpaceId), targetPosition);
        }

        private void OnReviseRequest(Connection sender, ReviseRequest msg)
        {
            Space space = sender.Get<Session>().Space;
            Character character=space.CharacterDict[msg.EntityId];
            character.Revive(character.entityId);
            space.CharacterLeave(sender, character);
        }

        private void OnCharacterUsingSkillRequest(Connection sender, NCharacterUsingSkillRequest msg)
        {
            var Character = sender.Get<Session>().Character;
            var list = Db.fsql.Select<DbUsingSkill>().Where(t => t.CharacterId == Character.entityId).ToList();
            List<int> skillID = new List<int>();
            NcharacterUsingSkillListResponse usingSkillListResponse = new NcharacterUsingSkillListResponse();
            //下面这里走的是服务器，现在不走服务器，开始就是假的
            //foreach (var item in list)
            //{
            //    skillID.Add(item.SkillId);
            //}
            //skillID.Sort();
            //for (int i = 0; i < skillID.Count; i++)
            //{
            //    usingSkillListResponse.UsingskillList.Add(skillID[i]);
            //    Log.Information("玩家携带的技能ID有" + skillID[i]);
            //}
            if (Character.jobId == 8)
            {
                for (int i = 4; i < 9; i++)
                {
                    if (i == 6) continue;
                    usingSkillListResponse.UsingskillList.Add(i);
                }
            }
            else if (Character.jobId == 2)
            {
                for (int i = 9; i < 13; i++)
                {
                    usingSkillListResponse.UsingskillList.Add(i);
                }
            }
            sender.Send(usingSkillListResponse);
        }

        private void OnCharacterDeleteRequest(Connection sender, CharacterDeleteRequest msg)
        {
            var player = sender.Get<Session>().DbPlayer;
            Db.fsql.Delete<DbCharacter>().Where(t=>t.Id==msg.CharacterId).Where(t=>t.PlayerId==player.Id).ExecuteAffrows();
            CharacterDeleteResponse deleteResponse = new CharacterDeleteResponse();
            deleteResponse.Success = true;
            deleteResponse.Message = "";
            sender.Send(deleteResponse);
        }

        private void OnCharacterListRequest(Connection sender, CharacterListRequest msg)
        {
            var player = sender.Get<Session>().DbPlayer;
            var list=Db.fsql.Select<DbCharacter>().Where(t=>t.PlayerId==player.Id).ToList();
            CharacterListResponse listResponse = new CharacterListResponse();
            foreach (var item in list)
            {
                listResponse.CharacterList.Add(new NCharacter()
                {
                    Id = item.Id,
                    Name = item.Name,
                    TypeId = item.JobId,
                    //EntityId
                    Level = item.Level,
                    Exp = item.Exp,
                    SpaceId = item.SpaceId,
                    Gold = item.Gold,
                    //Entity
                    Hp = item.Hp,
                    Mp = item.Mp,
                    Attack = item.Attack,
                    Defense = item.Defense,
                    Magic = item.Magic,
                    Speed = item.Speed,
                    Magicdefense = item.MagicDefense,
                    Baoji = item.Baoji,
                    Maxmp = item.MaxMp,
                    Maxhp=item.MaxHp,
                    Baojidefense = item.BaojiDefense
                }); ;
            }
            sender.Send(listResponse);
        }

        private void OnCharacterCreateRequest(Connection sender, CharacterCreateRequest msg)
        {
            var isExit = Db.fsql.Select<DbCharacter>().Where(t => t.Name == msg.Name).ToOne();
            Log.Information("查询了数据库，是否存在相同名字的结果是" + isExit);
            ChracterCreateResponse createResponse = new ChracterCreateResponse();
            if (isExit==null)
            {
                var player = sender.Get<Session>().DbPlayer;
                createResponse.Success = true;
                createResponse.Character = new NCharacter()
                {
                    Name = msg.Name,
                    TypeId = msg.JobType,
                    Hp = DataManager.Instance.CharacterMessageDict[msg.JobType].hp,
                    Mp = DataManager.Instance.CharacterMessageDict[msg.JobType].magic,
                    Level = 1,
                    Exp = 0,
                    SpaceId = 6,
                    Attack = DataManager.Instance.CharacterMessageDict[msg.JobType].attack,
                    Defense = DataManager.Instance.CharacterMessageDict[msg.JobType].defense,
                    Magic = DataManager.Instance.CharacterMessageDict[msg.JobType].magic,
                    Magicdefense = DataManager.Instance.CharacterMessageDict[msg.JobType].magicdefense,
                    Gold = 0,
                    Speed = DataManager.Instance.CharacterMessageDict[msg.JobType].speed,
                    Id = player.Id,
                    Baoji = DataManager.Instance.CharacterMessageDict[msg.JobType].baoji,
                    Maxhp = DataManager.Instance.CharacterMessageDict[msg.JobType].MaxHP,
                    Maxmp = DataManager.Instance.CharacterMessageDict[msg.JobType].MaxMp,
                    Baojidefense= DataManager.Instance.CharacterMessageDict[msg.JobType].baojidefense
                };
                createResponse.Message = "成功创建角色，请前往登陆页面进行登录";
                DbCharacter dbCharacter = new DbCharacter()
                {
                    Name = msg.Name,
                    JobId = msg.JobType,
                    Hp = DataManager.Instance.CharacterMessageDict[msg.JobType].hp,
                    Mp = DataManager.Instance.CharacterMessageDict[msg.JobType].mp,
                    Level = 1,
                    Exp = 0,
                    SpaceId = 6,
                    Attack = DataManager.Instance.CharacterMessageDict[msg.JobType].attack,
                    Defense = DataManager.Instance.CharacterMessageDict[msg.JobType].defense,
                    Magic = DataManager.Instance.CharacterMessageDict[msg.JobType].magic,
                    MagicDefense = DataManager.Instance.CharacterMessageDict[msg.JobType].magicdefense,
                    Gold = 0,
                    Speed = DataManager.Instance.CharacterMessageDict[msg.JobType].speed,
                    PlayerId = player.Id,
                    Baoji = DataManager.Instance.CharacterMessageDict[msg.JobType].baoji,
                    MaxHp = DataManager.Instance.CharacterMessageDict[msg.JobType].MaxHP,
                    MaxMp = DataManager.Instance.CharacterMessageDict[msg.JobType].MaxMp,
                    BaojiDefense = DataManager.Instance.CharacterMessageDict[msg.JobType].baojidefense
                };
                var RoleID= Db.fsql.Insert(dbCharacter).ExecuteAffrows();
                
                sender.Send(createResponse);
            }
            else
            {
                createResponse.Success = false;
                createResponse.Character = null;
                createResponse.Message = "已经有玩家叫这个名字了，换一个名称并重新创建试试";
                sender.Send(createResponse);
            }
        }

        private void OnUserRegisterRequest(Connection sender, UserRegisterRequest msg)
        {
            var isExit=Db.fsql.Select<DbPlayer>().Where(t => t.Username == msg.Username).ToOne();
            if(isExit==null)
            {
                //让数据库去添加用户刚刚注册的这个数据
                DbPlayer dbPlayer = new DbPlayer()
                {
                    Username = msg.Username,
                    Password = msg.Password,
                };
                var t1 = Db.fsql.Insert(dbPlayer).ExecuteAffrows();

                //告诉刚刚注册的客户端数据注册成功了
                UserRegisterResponse response = new UserRegisterResponse();
                response.Code = t1;
                response.Message = "注册成功请返回登录";
                sender.Send(response);
                Log.Information("这里的数据库插入返回值是" + t1);
            }
            else
            {
                UserRegisterResponse response = new UserRegisterResponse();
                response.Message = "注册失败，已经存在用户名相同用户，请更改用户名并重新注册";
                sender.Send(response);
                Log.Information("数据库里面已经有这个数据了");
            }
        }

        private void _GameEnterRequest(Connection conn, GameEnterRequest msg)
        {
            Log.Information("有玩家进入游戏"+"角色ID是"+msg.CharacterId);
            int entityId = EntityManager.Instance.NewEntityId;
            var player = conn.Get<Session>().DbPlayer;
            var dbRole=Db.fsql.Select<DbCharacter>().Where(t => t.Id == msg.CharacterId).Where(t => t.PlayerId == player.Id).First();

            Character character = CharacterManager.Instance.Create(dbRole);
            character.Data = dbRole;
            character.Data.Knapsack = character.knapsack.InventoryInfo.ToByteArray();
            character.Data.WareKnapsack=character.wareKnapsack.InventoryInfo.ToByteArray();
            NCharacter nCharacter = new NCharacter
            {
                Id = dbRole.Id,
                TypeId = dbRole.JobId,
                EntityId = entityId,
                Name = dbRole.Name,
                Level = dbRole.Level,
                Exp = dbRole.Exp,
                SpaceId = dbRole.SpaceId,
                Gold = dbRole.Gold,
                Hp = dbRole.Hp,
                Mp = dbRole.Mp,
                Attack = dbRole.Attack,
                Defense = dbRole.Defense,
                Magic = dbRole.Magic,
                Speed = dbRole.Speed,
                Magicdefense = dbRole.MagicDefense,
                Baoji = dbRole.Baoji,
                Baojidefense = dbRole.BaojiDefense,
                Maxhp=dbRole.MaxHp,
                Maxmp=dbRole.MaxMp,
                KnapsackInfo = character.Define.knapsackInfo
            };


            //通知玩家登录成功
            GameEnterResponse resp = new GameEnterResponse();
            resp.Success = true;
            resp.Entity = character.GetData();
            resp.Character = nCharacter;
            conn.Send(resp);
            //将新角色加入到地图
            var space = SpaceService.Instance.GetSpace(dbRole.SpaceId); //新手村
            space.CharacterJoin(conn, character, nCharacter);
        }


        //当消息分发器发现了UserLoginRequest类型数据，就会回调该方法
        private static void OnUserLoginRequest(Connection sender, UserLoginRequest msg)
        {
            var dbPlayer=Db.fsql.Select<DbPlayer>().Where(p => p.Username == msg.Username).Where(p => p.Password == msg.Password).First();
            UserLoginResponse resp = new UserLoginResponse();
            Log.Information("解析了登陆消息，结果是"+dbPlayer);
            if(dbPlayer==null)
            {
                resp.Success = false;
            }
            else
            {
                resp.Success = true;
                //sender.Set<DbPlayer>(dbPlayer);
                sender.Get<Session>().DbPlayer=dbPlayer;
            }
            sender.Send(resp);
        }
    }
}
